# 설치가 필요하다면 아래 문장으로 라이브러리 설치
# !pip pandas numpy matplotlib wordcloud bar_chart_race
import pandas as pd
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
import wordcloud
import bar_chart_race as bcr
import warnings
warnings.filterwarnings("ignore")
import matplotlib.font_manager as fm
font_list = fm.findSystemFonts(fontpaths = None, fontext = 'ttf')
font_list
# print([i for i in font_list if 'kr' in i])
font_location = '/Users/subinium/Library/Fonts/NotoSansCJKkr-Light.otf'
font_name = fm.FontProperties(fname=font_location).get_name()
# print(f'시각화에 사용한 폰트는 {font_name} 입니다.')
mpl.rc('font', family=font_name)
# 시각화를 위한 설정
pd.options.display.max_columns = 999
mpl.rcParams['figure.dpi'] = 300
mpl.rcParams['axes.spines.top'] = False
mpl.rcParams['axes.spines.right'] = False
base_ym
: 기준연월search_rank_nm
: 검색순위명srchwrd_nm
: 키워드viewss_co
: 조회수data = pd.read_csv('./ky_yngbgs_worry_rank_info_202012.csv')
data.head()
sn | base_ym | search_rank_nm | srchwrd_nm | views_co | pt_value | |
---|---|---|---|---|---|---|
0 | 1 | 201901 | 1 | 친구 | 69 | 24.21 |
1 | 2 | 201901 | 2 | 전학 | 20 | 7.02 |
2 | 3 | 201901 | 3 | 공부 | 15 | 5.26 |
3 | 4 | 201901 | 4 | 숨쉬기 | 13 | 4.56 |
4 | 5 | 201901 | 5 | 학원 | 11 | 3.86 |
# 데이터의 전체 기간
st, ed = data['base_ym'].min(), data['base_ym'].max()
print(f'{st}부터 {ed}까지 수집한 데이터입니다.')
# 고민 전체 조회수
total_views = data['views_co'].sum()
print(f'총 조회수는 {total_views}회입니다.')
# 고민 키워드 종류와 개수
total_keywords = data['srchwrd_nm'].nunique()
print(f'청소년이 검색하는 고민 키워드는 총 {total_keywords}개입니다.')
201901부터 202011까지 수집한 데이터입니다. 총 조회수는 8158회입니다. 청소년이 검색하는 고민 키워드는 총 208개입니다.
과연 청소년들은 어떤 고민들을 하고 있을까?
from PIL import Image
from wordcloud import WordCloud, STOPWORDS
# 전체 텍스트 데이터 전처리
total_text = (data['srchwrd_nm'] + ' ') * data['views_co']
total_text = ' '.join(total_text)
# 워드 클라우드 시각화
fig, ax = plt.subplots(figsize=(12, 8))
wordcloud = WordCloud(width = 1000, height = 600, random_state=1,
background_color='black',
colormap=mpl.cm.twilight,
collocations=False,
font_path=font_location,
stopwords = STOPWORDS).generate(total_text)
ax.imshow(wordcloud)
ax.axis('off')
plt.show()
fig, ax = plt.subplots(1, 1, figsize=(17, 8))
kwd_cnt = data.groupby('srchwrd_nm')['views_co'].sum().sort_values(ascending=False)[:60]
color_tot = sns.color_palette("twilight_shifted", 60)
kwd_color = {k:c for k, c in zip(kwd_cnt.index, color_tot)}
kwd_cnt = kwd_cnt[:20]
ax.bar(kwd_cnt.index, kwd_cnt,
color=sns.color_palette("twilight_shifted", 60)[:20],
width=0.55,
edgecolor='black',
linewidth=0.7)
ax.margins(0.02, 0.05)
for i in range(20):
ax.annotate(f'{kwd_cnt[i]}\n({kwd_cnt[i]/kwd_cnt.sum()*100:.3}%)', xy=(i, kwd_cnt[i]+70),
va='center', ha='center',
)
ax.set_ylim(0, 1790)
ax.set_title('청소년 고민 상위 20', weight='bold', fontsize=25, fontweight='bold')
ax.grid(axis='y', linestyle='-', alpha=0.4)
ax.set_ylabel('전체 조회수', fontsize=15)
ax.set_xlabel('키워드', fontsize=15)
fig.tight_layout()
plt.show()
친구(30.1%)에 대한 고민이 가장 많으며, 이후 전학(9.17%), 엄마(6.67%), 자퇴(5.41%), 관계(5.26%), 공부(5.1%), 생리(4.93%), 숨쉬기(3.95%), 임신(3.14%) 등의 순으로 고민이 많은 것을 확인할 수 있다.
친구에 대한 고민은 언제나 청소년 고민의 상위에 있는 것을 알 수 있으며, 다른 고민은 시간에 따라 변동성이 큰 것을 확인할 수 있다.
# data_rank
# base_ym 데이터를 문자열에서 날짜포맷으로 변경
data['base_ym'] = pd.to_datetime(data['base_ym'], format='%Y%m')
# 막대그래프 레이스를 위한 전처리
data_rank = pd.pivot_table(data, columns='srchwrd_nm', index='base_ym', values='views_co').fillna(0)
data_rank_percentage = pd.pivot_table(data, columns='srchwrd_nm', index='base_ym', values='pt_value').fillna(0)
bcr.bar_chart_race(df=data_rank,
n_bars=10,
period_length=800,
# dpi=200,
cmap='twilight',
filename=None)
month_rank = data.pivot(columns='search_rank_nm', index='base_ym', values='srchwrd_nm').iloc[:,0:20]
# 연속 구간 추출 함수
def continuous_seq(kwd):
arr = np.array(np.where(month_rank.values==kwd))
_, length = arr.shape
ret, st = [], 0
for i in range(1, length):
if arr[0, i-1]+1 != arr[0, i]:
ret.append(arr[:, st:i])
st = i
ret.append(arr[:, st:])
return ret
# 키워드 별 rank plot
def highlight(kwd, color, ax):
lsts = continuous_seq(kwd)
for lst in lsts:
ax.plot(lst[0,:], lst[1,:],
marker='o', ms=15, lw=2.5,
color=color, zorder=0)
ax.scatter(lst[0,:], lst[1,:],
marker='o', s=110,
color='white', zorder=10)
return ax
# 전체 rank plot
def ranking(kwds):
fig, axes = plt.subplots(2, 1, figsize=(30, 23))
ax = axes[0]
total_kwds = pd.Series(month_rank.values.flatten()).unique()
for kwd in total_kwds:
highlight(kwd, '#E0E0E0', ax)
color_tot = sns.color_palette("twilight_shifted", 14)[::2]
kwd_color = {k:c for k, c in zip(kwds, color_tot)}
for kwd in kwds:
highlight(kwd, kwd_color[kwd], ax)
ax.invert_yaxis()
ax.set_xticks(range(23))
ax.set_xticklabels(pd.to_datetime(month_rank.index, format='%Y%m').strftime('%m\n%Y'), fontweight='bold', fontsize=15)
ax.set_xlim(-0.2, 22.2)
ax.set_yticks(range(20))
ax.set_yticklabels([f'Rank {i}' for i in range(1, 21)], fontweight='bold', fontsize=15, color='gray')
ax.spines['left'].set_visible(False)
ax.spines['bottom'].set_visible(False)
title_tmp = ['\"'+k+'\"' for k in kwds]
ax.set_title(f'월별 {",".join(title_tmp)} 키워드 순위', weight='bold', fontsize=25, fontweight='bold')
ax = axes[1]
stack = pd.Series(np.ones(23))
for kwd in kwds:
b1 = ax.bar(range(23), data_rank_percentage[kwd], bottom=stack, color=kwd_color[kwd], width=0.6, label=kwd)
ax.bar_label(b1, label_type='center', color='white', fontsize=13, fmt='%.1f%%')
stack += data_rank_percentage[kwd].values
ax.set_xticks(range(23))
ax.set_xticklabels(pd.to_datetime(month_rank.index, format='%Y%m').strftime('%m\n%Y'), fontweight='bold', fontsize=15)
ax.set_xlim(-0.4, 22.4)
ax.set_yticks([])
ax.legend(fontsize=15)
ax.spines['left'].set_visible(False)
ax.set_title(f'월별 {",".join(title_tmp)} 키워드 비율', weight='bold', fontsize=25, fontweight='bold')
plt.show()
친구는 학생들의 매순간 1위 고민임을 확인할 수 있다.
ranking(['친구'])
학생의 본분은 공부인 만큼 다양한 키워드로 공부에 대한 고민들(약 9.7%)을 살펴볼 수 있다.
ranking(['공부', '시험', '학원'])
자퇴, 전학, 검정고시은 각각 2번째, 4번째, 19번째로 많은 고민 검색 키워드로 총 조회수의 약 17%를 차지하고 있다.
2019년에 비해 2020년에 자퇴와 전학에 대한 검색 키워드 조회수의 순위가 떨어진 것을 알 수 있다.
코로나 19로 인해 등교가 적어지고, 학업부담이 줄어들며 청소년들의 전학에 대한 고민이 비교적 후순위로 밀려난 것으로 보인다.
관련 기사
ranking(['전학', '자퇴', '검정고시'])
부모님과 관련된 고민은 시기적으로 큰 변화없이 전체 조회수에서 높은 순위, 높은 비율(약 11.8%)을 차지하고 있다.
ranking(['엄마', '아빠', '부모님'])
2019년에 비해 2020년에 임신에 대한 검색 조회수가 높아진 것을 확인할 수 있다.
국내에는 보고된 바가 없으나 해외의 경우 코로나로 인해 집에 있는 시간이 증가하며 청소년 임신이 증가했다는 사례가 있다.
관련기사
ranking(['임신'])
생리, 초경 키워드에 대한 순위나 전체 비율을 보았을 때, 2019년에 비해 2020년에 증가한 것을 확인할 수 있다.
성 관련 고민을 검색으로 찾는 비율의 증가는 코로나로 인한 성교육의 부재가 일부 영향이 있지 않았을까 예측해볼 수 있다.
관련기사
ranking(['생리', '초경'])
코로나 이전에도 주휴수당과 관련된 여러 의견이 있었지만, 코로나 이후 주휴수당에 대한 청소년의 고민도 상승한 것을 확인할 수 있다.
주휴수당에 대한 검색 결과가 2019년에는 큰 비중을 차지하지 않았지만 2020년 4월부터 9월까지는 매우 높은 순위를 차지한 것을 확인할 수 있다.
이런 결과가 나온 것은 다음과 같은 복합적인 요소에 대한 결과라고 생각할 수 있다.
해당 데이터가 고민 검색과 관련됨을 감안했을 때, 주휴수당과 관련하여 부당한 사례에 대한 검색이 주를 이루지 않았을까 하는 생각에 안타까운 마음도 든다.
관련기사
ranking(['주휴수당'])
ranking(['특성화고'])
자해와 우울증을 통합적으로 보았을 때, 순위표에서는 후순위에 있으나 매월 전체 고민의 1% 이상을 차지하고 있음을 확인할 수 있다.
그중에서도 10월에 우울증이 기존에 비해 1.5~2배 정도로 증가하는 것을 확인할 수 있다.
해당 고민 검색이 증가하는 이유는 크게 2가지로 볼 수 있다.
이를 해결하기 위해 꾸준한 청소년 심리 상담과 10월 부근으로 상담을 증가하는 등 정책적 고려가 필요해보인다.
관련기사
ranking(['자해', '우울증'])
그 외에도 숨쉬기라는 키워드가 높은 순위에 있다.
코로나가 유행하고 나서는 숨쉬는 것에 대한 두려움이라 생각할 수 있지만, 코로나 이전에도 많은 청소년들이 숨쉬기와 관련되어 고민 검색을 하였다.
청소년들이 숨쉬기에 대한 고민을 할 정도로 많은 고민과 스트레스를 받고 있다는 점이 안타깝다.
ranking(['숨쉬기', '스트레스'])
이번 분석을 통해 다음과 같은 청소년들의 고민을 좀 더 이해해볼 수 있다.